'libtcomm - Threaded communication channel for FreeBASIC
'Copyright (C) 2013  Ebben Feagan <sir@mud.owlbox.net>
'
'This library is free software; you can redistribute it and/or
'modify it under the terms of the GNU Lesser General Public
'License as published by the Free Software Foundation; either
'version 2.1 of the License, or (at your option) any later version.
'
'This library is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
'Lesser General Public License for more details.
'
'You should have received a copy of the GNU Lesser General Public
'License along with this library; if not, write to the Free Software
'Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include once "tcomm.bi"

constructor MData( byval dt as any ptr, byval frefun as sub( byval as any ptr ) ) export
    d = dt
    f = frefun
end constructor

destructor Message export
    if x <> 0 then delete x
end destructor

constructor Message( byval cm as integer, byval xtra as Mdata ptr = 0, byval cc as ComChannel_f ptr = 0 ) export
    this.c = cm
    this.x = xtra
    this.m = cc
end constructor

constructor Messages( byval rhs as Message ptr ) export
    this.d = rhs
    this.n = 0
end constructor

destructor Messages( ) export
    if this.d <> 0 then delete this.d
    if this.n <> 0 then delete this.n
end destructor

constructor CommChannel export
    _mutex = mutexcreate
end constructor

destructor CommChannel export
    if _mess <> 0 then delete _mess
    mutexdestroy _mutex
end destructor

sub CommChannel.send( byval m as Message ptr ) export
    mutexlock _mutex
    var nm = new Messages(m)
    var stepr = _mess
    var eol = stepr
    while stepr <> 0
        eol = stepr
        stepr = stepr->n
    wend
    if eol = 0 then
        _mess = nm
    else
        eol->n = nm
    end if
    mutexunlock _mutex
end sub

function CommChannel.recv( ) as Message ptr export
    dim res as Message ptr
    mutexlock _mutex
        if _mess = 0 then
            mutexunlock _mutex
            return 0
        end if
        var new_mess = _mess->n
        var old_mess = _mess
        _mess->n = 0
        res = _mess->d
        _mess->d = 0
        _mess = new_mess
    mutexunlock _mutex
    delete old_mess
    return res
end function
